﻿using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Linq;
using YNTK.Common.Const;
using YNTK.Common.Filter;
using YNTK.Common.Util;
using YNTK.Data.MongoDB.Repositorie;
using YNTK.Dependency;
using YNTK.DynamicApiController;
using YNTK.FriendlyException;
using YNTK.LinqBuilder;
using YNTK.System.Entitys.Dto.Resources;
using YNTK.System.Entitys.Resources;
using YNTK.System.Interfaces.Resources;
using YNTK.System.Entitys.Dto.Common;
using YNTK.Common.Enum;
using Shipeng.Util;
using YNTK.System.Interfaces.Permission;
using YNTK.Mapster;
using System.ComponentModel.DataAnnotations;

namespace YNTK.System.Service.Resources
{
    /// <summary>
    /// 管理体系认证业务范围服务
    /// 版 本：V1.0.0.0
    /// 版 权：云南通科科技有限公司（https://www.yntkkj.com）
    /// 作 者：李仕鹏
    /// 日 期：2022.10.30
    /// </summary>
    [ApiDescriptionSettings(Tag = "管理体系认证业务范围分类", Name = "BusinessScope", Order = 786)]
    [Route("api/[controller]")]
    public class BusinessScopeService: IBusinessScopeService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<BusinessScopeEntity> _repository;//管理体系认证业务范围分类仓储
        private readonly IMongoDBRepository<BusinessScopeEntity> _mongoDbRepository;//管理体系认证业务范围分类mongodb仓储
        private readonly ITkUsersService _tkUsersService;//用户服务
        private readonly HttpContext _httpContext;
        private readonly string _collection = "base_businessscope";//mongodb中管理体系认证业务范围分类数据集名称

        /// <summary>
        /// 构造方法依赖注入
        /// </summary>
        /// <param name="repository">管理体系认证业务范围分类仓储</param>
        /// <param name="mongoDbRepository">管理体系认证业务范围分类mongodb仓储</param>
        /// <param name="tkUsersService">用户服务</param>
        public BusinessScopeService(ISqlSugarRepository<BusinessScopeEntity> repository,
            IMongoDBRepository<BusinessScopeEntity> mongoDbRepository,
            ITkUsersService tkUsersService)
        {
            _repository = repository;
            _mongoDbRepository = mongoDbRepository;
            _tkUsersService = tkUsersService;
            _httpContext = App.HttpContext;
        }

        /// <summary>
        /// 获取管理体系认证业务范围类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("gettype")]
        public TkResult<List<EnumListDto>> GetTypeList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<BusinessScopeEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取管理体系认证业务范围分类树结构数据
        /// </summary>
        /// <param name="query">查询管理体系认证业务范围分类请求模型</param>
        /// <returns></returns>
        [HttpPost("gettrees")]
        public async Task<TkResult<List<BusinessScopeTreeDto>>> GetTrees([FromBody] QueryBusinessScopeFilterRequestModel query)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;

                #region 拼接查询条件
                Expression<Func<BusinessScopeEntity, bool>> where = m =>m.DeleteMark == null;
                //除运营平台账户外只能看启动状态的
                if (authenticationType != "0" && authenticationType != "1")
                    where = where.And(m => m.EnabledMark == 1);
                else
                {
                    if (query.enabledMark == 1) where = where.And(m => m.EnabledMark == 1);
                    if (query.enabledMark == 0) where = where.And(m => m.EnabledMark != 1);
                }
                if (query.type != null) where = where.And(m=>m.Type==query.type.GetHashCode());               
                if (query.startTime != null) where = where.And(m => m.CreatorTime >= query.startTime);
                if (query.endTime != null) where = where.And(m => m.CreatorTime <= query.endTime);
                if (!string.IsNullOrWhiteSpace(query.keyword))
                    where = where.And(m => m.Name.Contains(query.keyword) || m.EnglishName.Contains(query.keyword)
                    || m.Description.Contains(query.keyword));
                #endregion

                List<BusinessScopeEntity> data=null;
                #region 先从mongodb中获取
                data = await _mongoDbRepository.GetListAsync(_collection, where);
                #endregion
                if (!data.Any())
                {
                    #region 再从sqlserver中获取
                    data = await _repository.Entities.Where(where).ToListAsync();
                    #endregion
                }
                var treeList = data.Adapt<List<BusinessScopeTreeDto>>();

                #region 处理返回数据
                if (treeList.Any())
                {
                    var userIds = treeList.Select(r => r.creatorUserId).Distinct().ToList();
                    var users = await _tkUsersService.GetUserListByIds(userIds);
                    treeList.ForEach(item =>{
                        item.typeText= EnumHelper.GetEnumDescriptionString
                        (item.type, typeof(BusinessScopeEnum));
                        if (!string.IsNullOrWhiteSpace(item.creatorUserId))
                            item.creatorUserName = users?.FirstOrDefault(r => r.Id == item.creatorUserId)?.RealName;
                    });
                    treeList = treeList.ToTree().OrderBy(r => r.sortCode).OrderByDescending(r => r.creatorTime).ToList();
                }               
                #endregion

                return TkResult<List<BusinessScopeTreeDto>>.Success(treeList);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取管理体系认证业务范围分类树结构数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加管理体系认证业务范围分类
        /// </summary>
        /// <param name="input">添加管理体系认证业务范围分类请求模型</param>
        /// <returns></returns>
        [HttpPost("add")]
        public async Task Add([FromBody] AddBusinessScopeRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "0" && authenticationType != "1")
                    throw YNTKException.Oh(ErrorCode.D1016);

                if((await GetBusinessScopeInfoAsync(r=>r.Type==input.type.GetHashCode() && 
                r.ParentId==input.parentId && r.Name==input.name && r.DeleteMark==null)) !=null)
                    throw YNTKException.Oh(ErrorCode.Scope0001);
                if (!string.IsNullOrWhiteSpace(input.englishName) && (await GetBusinessScopeInfoAsync(r => 
                r.Type == input.type.GetHashCode() && r.ParentId==input.parentId && 
                r.EnglishName == input.englishName && r.DeleteMark==null)) != null)
                    throw YNTKException.Oh(ErrorCode.Scope0002);

                var entity = input.Adapt<BusinessScopeEntity>();
                entity.Type = input.type.GetHashCode();

                //保存到sqlserver
                var isOk = await _repository.Context.Insertable(entity)
                   .CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
                _ = isOk ?? throw YNTKException.Oh(ErrorCode.Scope0003);

                //保存到mongodb
                entity = isOk;
                var result = await _mongoDbRepository.AddAsync(entity, _collection);
                if (!result) throw YNTKException.Oh(ErrorCode.Scope0004);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加管理体系认证业务范围分类发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 修改管理体系认证业务范围分类
        /// </summary>
        /// <param name="input">修改管理体系认证业务范围分类请求模型</param>
        /// <returns></returns>
        [HttpPut("update")]
        public async Task Update([FromBody] UpdateBusinessScopeRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "0" && authenticationType != "1")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetBusinessScopeInfoAsync(r => r.Id == input.id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Scope0005);
                if ((await GetBusinessScopeInfoAsync(r => r.Type == input.type.GetHashCode() && 
                r.ParentId == input.parentId && r.Name == input.name && r.Id!=input.id && r.DeleteMark==null)) != null)
                    throw YNTKException.Oh(ErrorCode.Scope0001);
                if (!string.IsNullOrWhiteSpace(input.englishName) && (await GetBusinessScopeInfoAsync(r =>
                r.Type == input.type.GetHashCode() && r.ParentId == input.parentId && 
                r.EnglishName == input.englishName && r.Id!=input.id && r.DeleteMark==null)) != null)
                    throw YNTKException.Oh(ErrorCode.Scope0002);

                entity = input.Mapper(entity);
                entity.Type = input.type.GetHashCode();
                entity.LastModifyTime = DateTime.Now;
                entity.LastModifyUserId = userId;

                //保存到sqlserver
                var isOK = await _repository.Context.Updateable(entity)
               .IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Scope0006);

                //保存到mongodb
                var update = await _mongoDbRepository.UpdateAsync(entity, _collection, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Scope0007);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"修改管理体系认证业务范围分类发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除管理体系认证业务范围分类
        /// </summary>
        /// <param name="id">管理体系认证业务范围分类id</param>
        /// <returns></returns>
        [HttpDelete("delete/{id}")]
        public async Task Delete([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "0" && authenticationType != "1")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetBusinessScopeInfoAsync(r => r.Id ==id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Scope0005);

                //从sqlserver中删除
                var isOk = await _repository.Context.Deleteable(entity).ExecuteCommandAsync();
                if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.Scope0008);

                //从mongodb中删除
                var delete = await _mongoDbRepository.DeleteAsync(_collection, m => m.Id == id);
                if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.Scope0009);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除管理体系认证业务范围分类发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 更新管理体系认证业务范围分类(启用/禁用)
        /// </summary>
        /// <param name="id">管理体系认证业务范围分类id</param>
        /// <returns></returns>
        [HttpPut("state/{id}")]
        public async Task UpdateState([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "0" && authenticationType != "1")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetBusinessScopeInfoAsync(r => r.Id == id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Scope0005);

                //sqlserver更新状态
                var isOk = await _repository.Context.Updateable<BusinessScopeEntity>()
               .SetColumns(it => new BusinessScopeEntity()
               {
                   EnabledMark = SqlFunc.IIF(it.EnabledMark == 1, 0, 1),
                   LastModifyUserId = userId,
                   LastModifyTime = SqlFunc.GetDate()
               }).Where(it => it.Id == id).ExecuteCommandAsync();
                if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.Scope0010);

                //mongodb更新状态
                entity.EnabledMark = entity.EnabledMark == 1 ? 0 : 1;
                entity.LastModifyTime = DateTime.Now;
                entity.LastModifyUserId = userId;
                var update = await _mongoDbRepository.UpdateAsync(entity, _collection, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Scope0011);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"更新管理体系认证业务范围分类(启用/禁用)发生异常：{ex.Message}");
            }
        }



        /// <summary>
        /// 根据条件获取管理体系认证业务范围分类信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        private async Task<BusinessScopeEntity> GetBusinessScopeInfoAsync(Expression<Func<BusinessScopeEntity, bool>> where)
        {
            //从从mongodb中获取
            var entity = await _mongoDbRepository.GetAsync(_collection, where);
            //再从sqlserver中获取
            if (entity == null) entity = await _repository.FirstOrDefaultAsync(where);
            return entity;
        }



        /// <summary>
        /// 根据id获取管理体系认证业务范围分类信息
        /// </summary>
        /// <param name="id">id</param>
        /// <returns></returns>
        [NonAction]
        public async Task<BusinessScopeEntity> GetBusinessScopeInfoAsync(string id)
        {
            //先从mongodb中获取
            var entity = await _mongoDbRepository.GetAsync(_collection,m=>m.Id==id);
            //再从sqlserver中获取
            if (entity == null) entity = await _repository.FirstOrDefaultAsync(r=>r.Id==id);
            return entity;
        }

        /// <summary>
        /// 获取管理体系认证业务范围分类数据
        /// </summary>
        /// <param name="ids">管理体系认证业务范围分类id集合</param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<BusinessScopeEntity>> GetBusinessScopeListAsync(List<string> ids)
        {
            var result = new List<BusinessScopeEntity>();
            if (!ids.Any()) return result;
            Expression<Func<BusinessScopeEntity, bool>> where = r => ids.Contains(r.Id) && r.DeleteMark == null;

            //从mongodb中获取
            result = await _mongoDbRepository.GetListAsync(_collection, where);
            if (!result.Any())
            {
                //从sqlserver数据库中获取
                result = await _repository.Entities.Where(where).ToListAsync();
            }
            return result;
        }

        /// <summary>
        /// 处理管理体系认证业务范围分类id拼接上所有父级id
        /// </summary>
        /// <param name="id">分页id</param>
        /// <returns></returns>
        [NonAction]
        public async Task<string> GetIdAsync(string id)
        {
            if (id.Contains(",")) return id;
            var data = await _mongoDbRepository.GetListAsync(_collection, m =>  m.DeleteMark == null);
            if (!data.Any()) data = await _repository.Entities.Where(r =>r.DeleteMark == null).ToListAsync();
            if (!data.Any()) return id;
            //获取所有上级包括自己
            data = data.TreeWhere(r => r.Id == id, r => r.Id, r => r.ParentId);
            //顺序反转
            data.Reverse();
            var ids = data.Select(r => r.Id).ToList();
            id = string.Join(',', ids);
            return id;
        }
    }
}
